package com.third.device.mg.serialport.help

import com.third.device.mg.serialport.listener.ConnectListener
import com.third.device.mg.serialport.utils.SLog
import com.third.device.mg.serialport.utils.toHexString
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.functions.Consumer
import io.reactivex.rxjava3.schedulers.Schedulers
import java.io.InputStream
import java.io.OutputStream
import java.net.InetSocketAddress
import java.net.Socket

/**
 * company 广东玛格家居有限公司
 * @author smoker
 * @Date 2021/12/29
 * Description:单个Socket个体bean
 * 负责自己本身一些信息数据
 * @param ip      目标ip
 * @param port    目标端口
 */

@Deprecated("启用,采用Netty框架" ,ReplaceWith("SocketBootstrapManager"),DeprecationLevel.WARNING)
class SocketUnit(private val ip: String, private val port: Int) {
    //socket连接状态
    private var connectState = SocketUnitState.Disconnect

    //连接的Disposable
    private var connectDisposable: Disposable? = null

    //发送的Disposable
    private var writeDisposable: Disposable? = null

    //接收的Disposable
    private var readDisposable: Disposable? = null

    /*连接状态的监听*/
    private var connectListener: ConnectListener? = null

    companion object {
        private const val TAG = "SocketUnit: "
        fun createKey(ip: String, port: Int) = "${ip}:$port"
    }

    init {
        connectSocket()
    }

    private var mSocket: Socket? = null

    private var outputStream: OutputStream? = null

    private var inputStream: InputStream? = null


    fun getIP() = ip

    fun getPort() = port

    fun getAddress() = "${ip}:$port"

    fun addConnectListener(listener: ConnectListener) {
        this.connectListener = listener
    }

    /**
     * 刷新当前Socket的连接状态
     * 同时也回调到[connectListener]
     */
    fun refreshSocketState(): SocketUnitState {
        mSocket?.let {
            if (it.isConnected && !it.isOutputShutdown && !it.isClosed) {
                notifyConnectState(SocketUnitState.ConnectSuccess)
            } else {
                notifyConnectState(SocketUnitState.Disconnect)
            }
        } ?: notifyConnectState(SocketUnitState.Disconnect)
        return connectState
    }

    /**
     * 发送信息
     */
    fun write(data: ByteArray) {
        if (refreshSocketState() == SocketUnitState.ConnectSuccess) {
            writeData(data)
        }
    }


    /**
     * 连接Socket
     */
    fun connectSocket() {
        connectDisposable?.let {
            if (!it.isDisposed) {
                it.dispose()
            }
        }
        connectDisposable = Observable.create<SocketUnitState> { emitter ->
            emitter.onNext(SocketUnitState.Connecting)
            SLog.d(TAG, "正在链接: ${ip}:${port}")
            val socket = Socket()
            socket.connect(InetSocketAddress(ip, port), 10000)
            if (socket.isConnected && !socket.isClosed && !socket.isOutputShutdown) {
                mSocket = socket
                emitter.onNext(SocketUnitState.ConnectSuccess)
                SLog.d(TAG, "${ip}:${port}:连接成功")
            } else {
                mSocket?.let {
                    closeInput()
                    closeOutput()
                }
                emitter.onNext(SocketUnitState.ConnectError)
            }
            emitter.onComplete()
        }.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnNext {
                notifyConnectState(it)
                when (it) {
                    SocketUnitState.ConnectSuccess -> {
                        readData()
                    }
                    SocketUnitState.ConnectError -> {

                    }
                    else -> {

                    }
                }
            }
            .doOnError {
                notifyConnectState(SocketUnitState.ConnectError)
            }
            .subscribe()
    }


    /**
     * 写入信息
     */
    private fun writeData(data: ByteArray) {
        writeDisposable?.let {
            if (!it.isDisposed) {
                it.dispose()
            }
        }
        writeDisposable = Observable.create<SocketUnitState> { emitter ->
            mSocket?.let { socket ->
                socket.getOutputStream()?.let {
                    outputStream = it
                    it.write(data)
                    it.flush()
                    SLog.d(TAG, "${ip}:${port}:发送成功: ${data.toHexString()}")
                    emitter.onNext(SocketUnitState.WriteSuccess)
                } ?: let {
                    emitter.onNext(SocketUnitState.Disconnect)
                }
            } ?: let {
                emitter.onNext(SocketUnitState.Disconnect)
            }
            emitter.onComplete()
        }.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnNext {
                notifyConnectState(it)
            }
            .doOnError {
                notifyConnectState(SocketUnitState.ConnectError)
            }
            .subscribe()
    }


    /**
     * 接收服务器的信息
     */
    private fun readData() {
        readDisposable?.let {
            if (!it.isDisposed) {
                it.dispose()
            }
        }
        readDisposable = Observable.create<Any> { emitter ->
            mSocket?.let { socket ->
                socket.getInputStream()?.let { input ->
                    inputStream = input
                    val read = ByteArray(1024)
                    var len: Int
                    while ((input.read(read)).also { len = it } != -1) {
                        val result = ByteArray(len)
                        System.arraycopy(read, 0, result, 0, len)
                        emitter.onNext(result)
                    }
                } ?: let {
                    emitter.onNext(SocketUnitState.Disconnect)
                    emitter.onError(Throwable("输入流关闭了"))
                }
            } ?: let {
                emitter.onNext(SocketUnitState.Disconnect)
                emitter.onError(Throwable("Socket关闭了"))
            }
            emitter.onComplete()
        }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                when (it) {
                    is SocketUnitState -> {
                        notifyConnectState(it)
                    }
                    is ByteArray -> {
                        SLog.d(TAG, "${ip}:${port}:收到消息: ${it.toHexString()}")
                        notifyReadData(it)
                    }
                }
            } ,{
                it.printStackTrace()
                SLog.d(TAG ,"${ip}:${port}:Socket 断开连接")
                notifyConnectState(SocketUnitState.ConnectError)
            })
    }


    fun onDestroy() {
        closeInput()
        closeOutput()
        closeSocket()
    }

    private fun closeOutput() {
        mSocket?.let {
            if (!it.isClosed && !it.isOutputShutdown) {
                it.shutdownOutput()
            }
        }
        outputStream?.close()
        outputStream = null
    }

    private fun closeInput() {
        mSocket?.let {
            if (!it.isClosed && !it.isInputShutdown) {
                it.shutdownInput()
            }
        }
        inputStream?.close()
        inputStream = null
    }

    private fun closeSocket() {
        mSocket?.let {
            if (!it.isClosed) {
                it.close()
            }
        }
        mSocket = null
    }

    /**
     * 更新连接状态
     */
    private fun notifyConnectState(state: SocketUnitState) {
        connectState = state
        connectListener?.connectState(ip, port, connectState)
    }

    /**
     * 通知读取到新消息
     */
    private fun notifyReadData(data: ByteArray) {
        connectListener?.connectState(ip, port, SocketUnitState.ReadSuccess)
        connectListener?.readListener(ip, port, data)
    }

}